#include "mainwidget.h"
#include "ui_mainwidget.h"
#include "listwidgetitem.h"
#include "chatwidget.h"

#include "network/messageSocket.h"
#include "likeDatabase/likedatabase.h"
#include "config/globalconfig.h"
#include "network/filereader.h"
#include "network/filesender.h"

#include <QDebug>
#include <QFileDialog>
#include <QTime>
#include <QTcpServer>
#include <QCursor>
#include <QMenu>
#include <QInputDialog>
#include <QMessageBox>
#include <QSound>

MainWidget::MainWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MainWidget)
{
    ui->setupUi(this);
    //不要显示标题栏
    this->setWindowFlags(Qt ::FramelessWindowHint);
    //设置皮肤
    QFile file(":/qss/qss/styleBlack.qss");
    file.open(QIODevice::ReadOnly);
    QString s = file.readAll();
    file.close();
    this->setStyleSheet(s);
    //获取配置数据
    m_globalConfig = new GlobalConfig;
    ui->labPhoto->setPixmap(QPixmap(m_globalConfig->userPhotoPath()));
    ui->labName->setText(m_globalConfig->name());
    //初始化数据库
    m_database = new LikeDatabase;
    //连接双击和单击选中朋友信号
    connect(ui->btnSetStyleSheet, &QPushButton::clicked, this, &MainWidget::changeStyleSheet);
    connect(ui->friendListWidget, &QListWidget::itemDoubleClicked, this, &MainWidget::onItemDoubleClicked);
    //创建局域网通信接口并连接信号
    m_messageSocket = new MessageSocket(m_globalConfig->uuid(), this,
                                        m_globalConfig->broadcastPort(),
                                        m_globalConfig->udpPort());
    connect(m_messageSocket, &MessageSocket::hasExitMessage, this, &MainWidget::recvExitMessage);
    connect(m_messageSocket, &MessageSocket::hasLoginMessage, this, &MainWidget::recvLoginMessage);
    connect(m_messageSocket, &MessageSocket::hasNameMessage, this, &MainWidget::recvNameMessage);
    connect(m_messageSocket, &MessageSocket::hasPhotoMessage, this, &MainWidget::recvPhotoMessage);
    connect(m_messageSocket, &MessageSocket::hasTextMessage, this, &MainWidget::recvTextMessage);
    connect(m_messageSocket, &MessageSocket::hasEchoLoginMessage, this, &MainWidget::recvEchoLoginMessage);
    connect(m_messageSocket, &MessageSocket::hasImageMessage, this, &MainWidget::recvImageMessage);
    //创建接受文件客户端
    m_server = new QTcpServer(this);
    m_server->listen(QHostAddress::AnyIPv4, m_globalConfig->tcpPort());
    //连接接收新的Socket发送文件请求
    connect(m_server, &QTcpServer::newConnection, this, &MainWidget::onNewConnection);
    //发送登录信息
    m_messageSocket->sendLoginMessage(m_globalConfig->name());
    //发送头像
    m_messageSocket->sendPhotoMessage(QPixmap(m_globalConfig->userPhotoPath()));
    //把数据库中的朋友添加到界面上
    QVector<QPair<QString, QString> > vector = m_database->getAllUuidAndName();
    for(QPair<QString, QString> &t : vector){
        ListWidgetItem *item = new ListWidgetItem(t.first, ui->friendListWidget);
        item->setName(t.second);
        m_listWidgetItemMap.insert(t.first, item);
    }
    //设置friendListWidget右键菜单属性
    ui->friendListWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
    //添加右键菜单
    ui->friendListWidget->addAction(ui->actionDeleteChatRecord);
    ui->friendListWidget->addAction(ui->actionDeleteFriend);
    ui->friendListWidget->addAction(ui->actionSetName);
}
/********************这是MainWidget自己的槽函数**************************/
void MainWidget::onItemDoubleClicked(QListWidgetItem *item)
{
    ListWidgetItem *ptr = (ListWidgetItem*)item;
    ptr->changeStatusOnDoubleCliked();
    ChatWidgetMapIterator ite = m_chatWidgetMap.find(ptr->uuid());
    if(ite == m_chatWidgetMap.cend() || ite.value() == nullptr){
        //创建新的对话框并连接信号
        ChatWidget* chatWidget = new ChatWidget(ptr->uuid());
        chatWidget->setWindowTitle(ptr->name());
        chatWidget->show();
        //插入所有历史记录
        chatWidget->addHistoryMessage(m_database->getTopTenMessage(ptr->uuid()));
        //插入map中
        m_chatWidgetMap.insert(ptr->uuid(), chatWidget);
        //连接信号
        connect(chatWidget, &ChatWidget::redayClose, this, &MainWidget::thisUUidChatWidgetClosed);
        connect(chatWidget, &ChatWidget::sendFile, this, &MainWidget::sendFile);
        connect(chatWidget, &ChatWidget::sendMessage, this, &MainWidget::sendMessage);
        connect(chatWidget, &ChatWidget::sendImage, this, &MainWidget::sendImage);
    }
    else{
        //显示窗口
        ite.value()->setVisible(true);
    }
}
//切换皮肤
void MainWidget::changeStyleSheet()
{
    qDebug() << "准备更换皮肤";
    QString qssFile = ui->editQssFileName->text();
    if(qssFile.isEmpty()){
        qssFile = QFileDialog::getOpenFileName(this, "请选择你要使用皮肤文件",
                                                       QDir::currentPath(),
                                                       "*.qss");
        if(qssFile.isEmpty()){
            qDebug() << "没有选中几何文件";
            return;
        }
    }
    ui->editQssFileName->setText(qssFile);
    QFile file(qssFile);
    file.open(QIODevice::ReadOnly);
    QString s = file.readAll();
    file.close();
    this->setStyleSheet(s);
}
/*********************这是属于ChatWidget的槽函数开始*****************************/
void MainWidget::sendMessage(const QString &uuid, const QString &message)
{
    qDebug() << QString("向 %1 发送消息: %2").arg(uuid).arg(message);
    //发送消息
    m_messageSocket->sendText(uuid, message);
    //插入Sqlite数据库中
    m_database->addMessage(uuid, message, true);
}

void MainWidget::sendImage(const QString &uuid, const QString &imageName)
{
    m_messageSocket->sendImageMessage(uuid, QPixmap(imageName));
}

void MainWidget::thisUUidChatWidgetClosed(const QString &uuid)
{
    ChatWidgetMapIterator ite = m_chatWidgetMap.find(uuid);
    if(ite == m_chatWidgetMap.cend()){
        qDebug() << "thisUUidChatWidgetClosed(const QString &uuid) error";
        return;
    }
    qDebug() << "thisUUidChatWidgetClosed() :" << uuid;
    delete ite.value();
    ite.value() = nullptr;
}
//发送文件
void MainWidget::sendFile(const QString &uuid, const QString &fileName)
{
    if(fileName.isEmpty()){
        return;
    }
    QHostAddress addr = m_messageSocket->getHostAddress(uuid);
    FileSender *sender = new FileSender(addr.toString(), m_globalConfig->tcpPort()
                                        ,fileName, QByteArray(uuid.toUtf8()), this);
    Q_UNUSED(sender);
}
/********************ChatWidget槽函数结束******************/
//接收文件传输
void MainWidget::onNewConnection()
{
    QTcpSocket *socket = m_server->nextPendingConnection();
    FileReader *reader = new FileReader(socket, m_globalConfig->downloadPath(), this);
    Q_UNUSED(reader);
}
//把好友添加进朋友列表中
void MainWidget::addFriend(const QString &friendUuid, const QString &friendName)
{
    ListWidgetItemMapIterator ite = m_listWidgetItemMap.find(friendUuid);
    if(ite != m_listWidgetItemMap.cend()){
        //播放朋友上线音效
        this->playSound(SOUND_ONLINE);
        //把朋友移动到第0行
        int row = ui->friendListWidget->row(ite.value());
        ListWidgetItem * t = (ListWidgetItem*)ui->friendListWidget->takeItem(row);
        ui->friendListWidget->insertItem(0, t);
        //更新朋友网名
        m_database->updateFriendNetName(friendUuid, friendName);
        qDebug() << "朋友目录里已经有了";
        return;
    }
    else{
        //播放新朋友上线音效
        this->playSound(SOUND_NEWFRIEND);

        ListWidgetItem *item = new ListWidgetItem(friendUuid);
        item->setName(friendName);
        //插入到第一位置
        ui->friendListWidget->insertItem(0, item);
        //插入map中
        m_listWidgetItemMap.insert(friendUuid, item);
        //插入Sqlite数据库中
        m_database->addNewFriend(friendUuid, friendName);
    }
}

void MainWidget::playSound(MainWidget::SoundType type)
{
    switch (type) {
    case SOUND_ONLINE:
        QSound::play(":/sound/sound/onLine.wav");
        break;
    case SOUND_MESSAGE:
        QSound::play(":/sound/sound/message2.wav");
        return;
        break;
    case SOUND_NEWFRIEND:
        QSound::play(":/sound/sound/newFriend.wav");
        break;
    default:
        qDebug() << "无效音效类型";
        return;
        break;
    }
}
/******************以下为接受消息函数MessageSocket槽函数******************/
//登录消息
void MainWidget::recvLoginMessage(const QString &friendUuid, const QString &friendName)
{
    //返回响应登录消息
    m_messageSocket->sendEchoLoginMessage(friendUuid, m_globalConfig->name());
    //把好友加入列表中
    this->addFriend(friendUuid, friendName);
    qDebug() << QString("收到name(%1),uuid(%2)的登录消息").arg(friendName).arg(friendUuid);
    //发送头像
    m_messageSocket->sendPhotoMessage(friendUuid, QPixmap(m_globalConfig->userPhotoPath()));

}
//响应登录消息
void MainWidget::recvEchoLoginMessage(const QString &friendUuid, const QString &friendName)
{
    //把好友加入列表中
    this->addFriend(friendUuid, friendName);
}

void MainWidget::recvTextMessage(const QString &friendUuid, const QString &text)
{
    ListWidgetItemMapIterator itemIte = m_listWidgetItemMap.find(friendUuid);
    if(itemIte == m_listWidgetItemMap.cend()){
        qDebug() << QString("接受到UUID(%1) : %2. 它不在好友列表中")
                        .arg(friendUuid)
                        .arg(text);
        return;
    }
    //插入Sqlite数据库中
    m_database->addMessage(friendUuid, text, false);
    //播放新消息音效
    this->playSound(SOUND_MESSAGE);
    //有对话窗就把消息传给对话框，没有设置对应的ListWidgetItem状态
    ChatWidgetMapIterator ite = m_chatWidgetMap.find(friendUuid);
    if(ite == m_chatWidgetMap.cend() || ite.value() == nullptr){
        itemIte.value()->changeStatusOnHasNewMessage();
    }
    else{
        ite.value()->addNewMessage(text);
    }
}

void MainWidget::recvNameMessage(const QString &friendUuid, const QString &friendName)
{
    ListWidgetItemMapIterator ite = m_listWidgetItemMap.find(friendUuid);
    if(ite == m_listWidgetItemMap.cend()){
        qDebug() << QString("收到来自UUID(%1)的更名请求, 它不在好友列表中");
        return;
    }

    m_database->updateFriendNetName(friendUuid, friendName);
}

void MainWidget::recvPhotoMessage(const QString &friendUuid, const QPixmap &friendPhoto)
{
    ListWidgetItemMapIterator ite = m_listWidgetItemMap.find(friendUuid);
    if(ite == m_listWidgetItemMap.cend()){
        qDebug() << QString("收到来自UUID(%1)的更新照片, 它不在好友列表中");
        return;
    }
    qDebug() << QString("收到来自UUID(%1)的更新照片消息");
    ite.value()->setPhoto(QIcon(friendPhoto));
}

void MainWidget::recvImageMessage(const QString &friendUuid, const QImage &image)
{
    ListWidgetItemMapIterator itemIte = m_listWidgetItemMap.find(friendUuid);
    if(itemIte == m_listWidgetItemMap.cend()){
        qDebug() << QString("接受到UUID(%1)的消息. 它不在好友列表中")
                        .arg(friendUuid);
        return;
    }
    //播放新消息音效
    this->playSound(SOUND_MESSAGE);
    //有对话窗就把消息传给对话框，没有设置对应的ListWidgetItem状态
    ChatWidgetMapIterator ite = m_chatWidgetMap.find(friendUuid);
    if(ite == m_chatWidgetMap.cend() || ite.value() == nullptr){
        itemIte.value()->changeStatusOnHasNewMessage();
    }
    else{
        ite.value()->addNewMessage(image);
    }
}

void MainWidget::recvExitMessage(const QString &friendUuid)
{
    ListWidgetItemMapIterator ite = m_listWidgetItemMap.find(friendUuid);
    if(ite == m_listWidgetItemMap.cend()){
        qDebug() << QString("收到来自UUID(%1)的离线消息, 它不在好友列表中");
        return;
    }
    ite.value()->changeStatusOnExit();
}

/*****************************以下函数不做修改*******************************/
MainWidget::~MainWidget()
{
    //发送退出消息
    m_messageSocket->sendExitMessage();
    delete ui;
}

void MainWidget::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);
    //关闭掉所有子窗口
    foreach (ChatWidget *ptr, m_chatWidgetMap) {
        if(ptr != nullptr){
          delete ptr;
        }
    }
}

void MainWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton){
        //改变指针形状
        QCursor cursor;
        cursor.setShape(Qt::ClosedHandCursor);
        QApplication::setOverrideCursor(cursor);
        //获取鼠标指针与窗口的差值
        m_offset = event->globalPos() - pos();
    }
}

void MainWidget::mouseReleaseEvent(QMouseEvent *event)
{
    Q_UNUSED(event);
    //恢复指针形状
    QApplication::restoreOverrideCursor();
}

void MainWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton){
        QPoint temp = event->globalPos() - m_offset;
        move(temp);
    }
}

//以下三个是切换窗口函数
void MainWidget::on_btnFriend_clicked()
{
    ui->stackedWidget->setCurrentIndex(0);
}

void MainWidget::on_btnGroup_clicked()
{
    ui->stackedWidget->setCurrentIndex(1);
}

void MainWidget::on_btnSet_clicked()
{
    //设置当前设置参数
    ui->editDownloadPath->setText(m_globalConfig->downloadPath());
    ui->spinBoxBroadcastPort->setValue(m_globalConfig->broadcastPort());
    ui->spinBoxTcpPort->setValue(m_globalConfig->tcpPort());
    ui->spinBoxUdpPort->setValue(m_globalConfig->udpPort());
    //切换界面
    ui->stackedWidget->setCurrentIndex(2);
}

//friendListWidget右键菜单槽函数
void MainWidget::on_actionDeleteFriend_triggered()
{
    ListWidgetItem *item = dynamic_cast<ListWidgetItem*>(ui->friendListWidget->currentItem());
    int index = ui->friendListWidget->currentRow();
    //从列表界面中删除好友
    ui->friendListWidget->takeItem(index);
    //删除好友
    m_database->deleteFriend(item->uuid());
    delete item;
}

void MainWidget::on_actionDeleteChatRecord_triggered()
{
    ListWidgetItem *item = dynamic_cast<ListWidgetItem*>(ui->friendListWidget->currentItem());
    m_database->deleteFriendChatRecord(item->uuid());
}

void MainWidget::on_actionSetName_triggered()
{
    ListWidgetItem *item = dynamic_cast<ListWidgetItem*>(ui->friendListWidget->currentItem());
    QString uuid = item->uuid();
    QString newName = QInputDialog::getText(this, "设置备注名", "请输入备注名:");
    if(!newName.isEmpty()){
        item->setName(newName);
        m_database->updateFriendName(uuid,newName);
    }
}
//用户网名右键设置槽函数
void MainWidget::on_labName_customContextMenuRequested(const QPoint &pos)
{
    Q_UNUSED(pos);
    QString newName = QInputDialog::getText(this, "设置新网名", "请输入网名:");
    if(!newName.isEmpty()){
        ui->labName->setText(newName);
        m_globalConfig->setName(newName);
        m_messageSocket->sendNameMessage(newName);
    }
}
//用户修改签名右键设置槽函数
void MainWidget::on_labAutograph_customContextMenuRequested(const QPoint &pos)
{
    Q_UNUSED(pos);
    QString autograph = QInputDialog::getText(this, "设置新的个性签名", "请输入签名:");
    if(!autograph.isEmpty()){
        ui->labName->setText(autograph);
        m_globalConfig->setAutograph(autograph);
    }
}
//用户修改头像设置槽函数
void MainWidget::on_labPhoto_customContextMenuRequested(const QPoint &pos)
{
    Q_UNUSED(pos);
    QString photoPath = QFileDialog::getOpenFileName(this, "请选择新的头像", QString()
                                                     ,"*.jpg; *.png");
    if(photoPath.isEmpty()){
        return;
    }

    QPixmap pixmap(photoPath);
    ui->labPhoto->setPixmap(pixmap);
    m_messageSocket->sendPhotoMessage(pixmap);
}
//设置界面配置槽函数
void MainWidget::on_btnDownloadPath_clicked()
{
    QString path = QFileDialog::getExistingDirectory(this, "请选择下载目录");
    if(!path.isEmpty()){
        ui->editDownloadPath->setText(path);
        m_globalConfig->setDownloadPath(path);
    }
}

void MainWidget::on_btnTcpPort_clicked()
{
    m_globalConfig->setTcpPort(ui->spinBoxTcpPort->value());
}

void MainWidget::on_btnBroadcastPort_clicked()
{
    if(ui->spinBoxBroadcastPort->value() == m_globalConfig->udpPort()){
        QMessageBox::warning(this, "警告", "你设置的广播端口号与Udp端口号相同！");
        return;
    }
    m_globalConfig->setBroadcastPort(ui->spinBoxBroadcastPort->value());
}

void MainWidget::on_btnUdpPort_clicked()
{
    if(ui->spinBoxUdpPort->value() == m_globalConfig->broadcastPort()){
        QMessageBox::warning(this, "警告", "你设置的Udp端口号与广播端口号相同！");
        return;
    }
    m_globalConfig->setUdpPort(ui->spinBoxUdpPort->value());
}
